package main

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/go-chi/chi/v5"
	"github.com/go-chi/chi/v5/middleware"
	"github.com/jackc/pgx/v5"
	"log"

	"net/http"
	"os"
	"svelete-demo/controller"
	"time"
)

//var dbConn *pgx.Conn

// func connectDb() {
//
//		dbUser := "cstuser"
//		dbPwd := "cst3721"
//		db := "kdb"
//		dbPort := "16900"
//		dbHost := "qnear.cn"
//		var err error
//		url := fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=require",
//			dbUser, dbPwd, dbHost, dbPort, db)
//		dbConn, err = pgx.Connect(context.Background(), url)
//		if err != nil {
//			msg := fmt.Sprintf("Unable to connect to database: %v\n", err)
//			fmt.Println(msg)
//			os.Exit(-1)
//			return
//		}
//		s := "create table if not exists t_user(id serial primary key,name varchar(32),cert varchar(32))"
//		_, err = dbConn.Exec(context.Background(), s)
//		if err != nil {
//			msg := fmt.Sprintf("Unable to connect to database: %v\n", err)
//			fmt.Println(msg)
//			os.Exit(-1)
//			return
//		}
//
//		fmt.Printf("connected to %s successfully\n", dbHost)
//	}
var (
	dbConn       *pgx.Conn
	userList     []*controller.User
	userLoggedIn []*controller.UserToken
)

//	func login(name, passwd string) {
//		s := "select * from t_user where name = :1, passwd = :2"
//		rows, err := dao.dbConn.Exec(context.Background(), s, name, passwd)
//		if err != nil {
//			msg := fmt.Sprintf("Unable to connect to database: %v\n", err)
//			fmt.Println(msg)
//			os.Exit(-1)
//			return
//		}
//		count := 0
//		for rows.Next() {
//			var email, pwd string
//			rows.Scan(&email, &pwd)
//			count++
//		}
//		if count > 0 {
//			fmt.Println("Login Sucessful!\n")
//		} else {
//			msg := fmt.Sprintf("user not exists or password incorrect!: %v\n", err)
//			fmt.Println(msg)
//			os.Exit(-1)
//			return
//		}
//	}
//
//	func register(name, passwd string) {
//		s := "select * from t_user where name = :1"
//		rows, err := dbConn.Exec(context.Background(), s, name)
//		if err != nil {
//			msg := fmt.Sprintf("Unable to connect to database: %v\n", err)
//			fmt.Println(msg)
//			os.Exit(-1)
//			return
//		}
//		count := 0
//		for rows.Next() {
//			var email, pwd string
//			rows.Scan(&email, &pwd)
//			count++
//		}
//		if count > 0 {
//			msg := fmt.Sprintf("user name already exists!: %v\n", err)
//			fmt.Println(msg)
//			os.Exit(-1)
//			return
//		} else {
//			s := "insert into t_user values(:1, :2, :3)"
//			_, err := dbConn.Exec(context.Background(), s, 1, name, passwd)
//			if err != nil {
//				msg := fmt.Sprintf("Unable to connect to database: %v\n", err)
//				fmt.Println(msg)
//				os.Exit(-1)
//				return
//			}
//			fmt.Printf("register sucessful")
//		}
//	}
func connectDb() {

	dbUser := "cstuser"
	dbPwd := "cst3721"
	db := "kdb"
	dbPort := "16900"
	dbHost := "qnear.cn"
	var err error
	url := fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=require",
		dbUser, dbPwd, dbHost, dbPort, db)
	dbConn, err = pgx.Connect(context.Background(), url)
	if err != nil {
		msg := fmt.Sprintf("Unable to connect to database: %v\n", err)
		fmt.Println(msg)
		os.Exit(-1)
		return
	}
	s := "create table if not exists t_user(id serial primary key,name varchar(32),cert varchar(32))"
	_, err = dbConn.Exec(context.Background(), s)
	if err != nil {
		msg := fmt.Sprintf("Unable to connect to database: %v\n", err)
		fmt.Println(msg)
		os.Exit(-1)
		return
	}

	fmt.Printf("connected to %s successfully\n", dbHost)
}

func selectUserDB(userd int64) (muserList []*controller.User, err error) {
	s := "select * from ctuser.t_user where id==$1"
	rows, err := dbConn.Query(context.Background(), s, userd)
	if err != nil {
		msg := fmt.Sprintf("Get user failed!: %v\n", err)
		fmt.Println(msg)
		os.Exit(-1)
		return nil, err
	}
	defer rows.Close()
	var nm, ct string
	var mid int64
	for rows.Next() {
		rows.Scan(&mid, &nm, &ct)
		tmpUser := controller.User{mid, nm, ct}
		muserList = append(muserList, &tmpUser)
	}
	fmt.Println("the userInfo len is: &d\n", len(muserList))
	return
}

func selectUserDBName(name string) (muserList []*controller.User, err error) {
	s := "select * from cstuser.t_user where name=$1"
	fmt.Printf("the select name is:%s\n", name)
	rows, err := dbConn.Query(context.Background(), s, name)
	if err != nil {
		msg := fmt.Sprintf("Get user failed!: %v\n", err)
		fmt.Println(msg)
		os.Exit(-1)
		return nil, err
	}
	defer rows.Close()
	var nm, ct string
	var mid int64
	for rows.Next() {
		rows.Scan(&mid, &nm, &ct)
		tmpUser := controller.User{mid, nm, ct}
		muserList = append(muserList, &tmpUser)
	}
	fmt.Println("the userInfo len is: ", len(muserList))
	return
}

func insertDb(name, cert string) {
	s := "insert into t_user(id, name, cert) values(DEFAULT, $1, $2)"
	_, err := dbConn.Exec(context.Background(), s, name, cert)
	if err != nil {
		msg := fmt.Sprintf("Insert failed!: %v\n", err)
		fmt.Println(msg)
		os.Exit(-1)
		return
	}
	fmt.Println("insert sucess!")
}

var msgCnn chan string

func sseHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Content-Type", "text/event-stream")
	w.Header().Set("Connection", "keep-alive")

	msgCnn = make(chan string)

	defer func() {
		close(msgCnn)
		msgCnn = nil
		fmt.Println("Client closed connection")
	}()

	flusher, ok := w.(http.Flusher)
	if !ok {
		fmt.Println("Could not init http.Flusher")
	}
	for {
		select {
		case message := <-msgCnn:
			fmt.Fprintf(w, "data: %s\n\n", message)
			flusher.Flush()
		case <-r.Context().Done():
			fmt.Println("Client closed connection")
			return
		}
	}
}

func getUser(w http.ResponseWriter, r *http.Request) {
	//w.Header().Set("Access-Control-Allow-Origin", "*")
	//w.Header().Set("Content-Type", "application/json")
	body := controller.UserMount{}
	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Printf("onMount error decoding body into struct %v\n", err)
		return
	}
	idx := len(userLoggedIn) - 1
	if idx < 0 {
		idx = 0
	}
	w.WriteHeader(http.StatusOK)
	if body.UserId == -1 {
		res := controller.UserLoginResponse{UserId: userLoggedIn[idx].UserId, UserName: userLoggedIn[idx].UserName, Token: userLoggedIn[idx].UserName + userLoggedIn[idx].UserPasswd, Status: 200}
		j, err := json.Marshal(res)
		if err != nil {
			fmt.Printf("onMount error parsing json: %v\n", err)
		}
		w.Write(j)
	} else {
		res := controller.UserLoginResponse{Status: 201}
		j, err := json.Marshal(res)
		if err != nil {
			fmt.Printf("onMount error parsing json: %v\n", err)
		}
		w.Write(j)
	}
	//} else {
	//	us, err := selectUserDB(body.UserId)
	//	if err != nil {
	//		fmt.Printf("onMount select failed: %v\n", err)
	//	}
	//	res := controller.UserLoginResponse{UserId: us[0].Id, Token: "111", Status: 200}
	//	j, err := json.Marshal(res)
	//	if err != nil {
	//		fmt.Printf("onMount error parsing json: %v\n", err)
	//	}
	//	w.Write(j)
	//}

	//w.Header().Set("Connection", "keep-alive")
	//var err error
	//var err error
	//userList, err = selectUserDB()
	//if err != nil {
	//	//panic(err)
	//	msg := http.StatusOK
	//	data, err := json.Marshal(msg)
	//	if err != nil {
	//		fmt.Println("Marshall error!")
	//	}
	//	status, merr := w.Write(data)
	//	if merr != nil {
	//		fmt.Println(merr)
	//	}
	//	fmt.Println(status)
	//}
	//msgCnn = make(chan string)
	//
	//defer func() {
	//	close(msgCnn)
	//	msgCnn = nil
	//	fmt.Println("Client closed connection")
	//}()
	//
	//flusher, ok := w.(http.Flusher)
	//if !ok {
	//	fmt.Println("Could not init http.Flusher")
	//}
	//for {
	//	select {
	//	case message := <-msgCnn:
	//		fmt.Fprintf(w, "data: %s\n\n", message)
	//		flusher.Flush()
	//	case <-r.Context().Done():
	//		fmt.Println("Client closed connection")
	//		return
	//	}
	//}
}

func getTime(w http.ResponseWriter, r *http.Request) {
	//w.Header().Set("Access-Control-Allow-Origin", "*")
	if msgCnn != nil {
		msg := time.Now().Format("15.04.05")
		msgCnn <- msg
	}
}

func getLogin(w http.ResponseWriter, r *http.Request) {
	body := controller.User{}
	//w.Header().Set("Access-Control-Allow-Origin", "*")
	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Printf("error decoding body into struct %v", err)
		log.Printf("error decoding body into struct %v", err)
		return
	}

	//jsonFile, err := os.Open(JSONFilePath)
	fmt.Printf("the getLogin body.Name is: %s\n", body.Name)
	muserList, err := selectUserDBName(body.Name)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Printf("Error reding tasks json file %v", err)
		log.Printf("error reading tasks json file %v", err)
		return
	}

	//tasks := []controller.User{}
	//if err := json.NewDecoder(jsonFile).Decode(&tasks); err != nil {
	//	w.WriteHeader(http.StatusInternalServerError)
	//	log.Printf("error decoding json file intro struct %v", err)
	//	return
	//}
	//
	//taskID, err := strconv.Atoi(chi.URLParam(r, "taskID"))
	//if err != nil {
	//	w.WriteHeader(http.StatusInternalServerError)
	//	log.Printf("error converting taskID from string into integer %v", err)
	//	return
	//}
	//
	//for i, task := range tasks {
	//	if task.ID == taskID {
	//		if body.Name != nil {
	//			task.Name = *body.Name
	//		}
	//
	//		if body.Done != nil {
	//			task.Done = *body.Done
	//		}
	//
	//		tasks[i] = task
	//	}
	//}
	//
	//j, err := json.Marshal(tasks)
	//if err != nil {
	//	w.WriteHeader(http.StatusInternalServerError)
	//	log.Printf("error marshalling tasks %v", err)
	//	return
	//}
	//
	//err = ioutil.WriteFile(JSONFilePath, j, 0755)
	if muserList == nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Printf("error writing tasks json file %v", err)
		log.Printf("error writing tasks json file %v", err)
		return
	}

	w.WriteHeader(http.StatusOK)
	j, err := json.Marshal(controller.UserLoginResponse{UserId: muserList[0].Id, UserName: muserList[0].Name, Token: muserList[0].Name + muserList[0].Password, Status: 200})
	fmt.Printf("the token is: %s\n", muserList[0].Name+muserList[0].Password)
	if err != nil {
		fmt.Printf("login json Marshal error: %v\n", err)
	}
	userLoggedIn = append(userLoggedIn, &controller.UserToken{UserId: muserList[0].Id, UserName: muserList[0].Name, UserPasswd: muserList[0].Password})
	w.Write(j)
	////proto := r.Proto
	////fmt.Println(proto)
	//w.Header().Set("Access-Control-Allow-Origin", "http://localhost:5173")
	//
	////if msgCnn != nil {
	////	msg := time.Now().Format("15.04.05")
	////	msgCnn <- msg
	////}
	//
	////userList, err = selectUserDB()
	//
	//msg := http.StatusOK
	//data, err := json.Marshal(msg)
	//if err != nil {
	//	fmt.Println("Marshall error!")
	//}
	//status, merr := w.Write(data)
	//if merr != nil {
	//	fmt.Println(merr)
	//}
	//fmt.Println(status)
}

func deleteUserLoggedin(id int64) []*controller.UserToken {
	var i int
	var userLogged []*controller.UserToken
	for i = 1; i < len(userLoggedIn); i++ {
		if userLoggedIn[i].UserId != id {
			userLogged = append(userLogged, userLoggedIn[i])
		}
	}
	return userLogged
}
func getLogout(w http.ResponseWriter, r *http.Request) {
	body := controller.User{}
	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Printf("error decoding body into struct %v", err)
		log.Printf("error decoding body into struct %v", err)
		return
	}
	userLoggedIn = deleteUserLoggedin(body.Id)
}
func getRegister(w http.ResponseWriter, r *http.Request) {
	//fmt.Println(r.Form)
	////w.Header().Set("Access-Control-Allow-Origin", "*")
	//if msgCnn != nil {
	//	msg := time.Now().Format("15.04.05")
	//	msgCnn <- msg
	//}

	body := controller.User{}
	//w.Header().Set("Access-Control-Allow-Origin", "*")
	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Printf("error decoding body into struct %v", err)
		log.Printf("error decoding body into struct %v", err)
		return
	}

	//jsonFile, err := os.Open(JSONFilePath)
	fmt.Printf("the getRegister body.Name is: %s\n", body.Name)
	muserList, err := selectUserDBName(body.Name)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Printf("Error reding tasks json file %v", err)
		log.Printf("error reading tasks json file %v", err)
		return
	}

	//if muserList != nil {
	//	w.WriteHeader(http.StatusOK)
	//	fmt.Printf("error writing tasks json file %v", err)
	//	log.Printf("error writing tasks json file %v", err)
	//	return
	//}
	w.WriteHeader(http.StatusOK)
	if len(muserList) > 0 {
		fmt.Printf("the user already registeed!")

		j, err := json.Marshal(controller.UserLoginResponse{Status: 201})
		//fmt.Printf("the token is: %s\n", muserList[0].Name+muserList[0].Password)
		if err != nil {
			fmt.Printf("register json Marshal error: %v\n", err)
		}
		//userLoggedIn = append(userLoggedIn, &controller.UserToken{UserId: muserList[0].Id, UserName: muserList[0].Name, UserPasswd: muserList[0].Password})
		w.Write(j)
	} else {
		insertDb(body.Name, body.Password)
		j, err := json.Marshal(controller.UserLoginResponse{Status: 200})
		//fmt.Printf("the token is: %s\n", muserList[0].Name+muserList[0].Password)
		if err != nil {
			fmt.Printf("register json Marshal error: %v\n", err)
		}
		//userLoggedIn = append(userLoggedIn, &controller.UserToken{UserId: muserList[0].Id, UserName: muserList[0].Name, UserPasswd: muserList[0].Password})
		w.Write(j)
	}

}

//func getUser(w http.ResponseWriter, r *http.Request) {
//	fmt.Println(r.Form)
//	w.Header().Set("Access-Control-Allow-Origin", "*")
//	if msgCnn != nil {
//		msg := time.Now().Format("15.04.05")
//		msgCnn <- msg
//	}
//}

// func
func JSONMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		w.Header().Set("Access-Control-Allow-Methods", "POST,GET,PATCH,DELETE,PUT")
		next.ServeHTTP(w, r)
	})
}
func main() {
	//go service.RunMessageServer()
	connectDb()

	r := chi.NewRouter()

	r.Use(middleware.Logger)

	r.Use(JSONMiddleware)

	r.Get("/", func(w http.ResponseWriter, _ *http.Request) {
		w.Write([]byte("Hello World!"))
	})

	r.Post("/user", getUser)

	r.Post("/register", getRegister)

	r.Post("/login", getLogin)
	r.Post("/logout", getLogout)
	//r.Patch("/tasks/{taskID}", updateTask)

	//r.Delete("/tasks/{taskID}", deleteTask)

	//c := cors.New(cors.Options{
	//	AllowedOrigins: []string{"http://localhost:5173"},
	//	AllowedMethods: []string{http.MethodGet, http.MethodPost, http.MethodDelete, http.MethodPatch},
	//})
	//
	//handler := c.Handler(r)

	http.ListenAndServe("localhost:5200", r)
	//router := http.NewServeMux()
	//
	//router.HandleFunc("/login", getLogin)
	//router.HandleFunc("/register", getRegister)
	//router.HandleFunc("/event", sseHandler)
	//router.HandleFunc("/user", getUser)
	//
	//go service.RunMessageServer()
	//insertDb("lll", "123")
	// 注册路由
	//r := routers.SetupRouter()
	//if err := r.Run(fmt.Sprintf(":%d", "5173")); err != nil {
	//	fmt.Printf("server startup failed, err:%v\n", err)
	//}
	//r := server.StartServer()
	//r.Run()

	//log.Fatal(http.ListenAndServe(":5200", router))
	//if err := router.Run(fmt.Sprintf(":%d", setting.Conf.Port)); err != nil {
	//	fmt.Printf("server startup failed, err:%v\n", err)
	//}
}
